package com.tianci.appstore.controller.manager;

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.os.RemoteException;
import android.provider.Settings;
import android.util.Log;

import com.coocaa.x.framework.app.CoocaaApplication;
import com.coocaa.x.framework.utils.LogUtils;
import com.coocaa.x.framework.utils.Storage;
import com.coocaa.x.framework.utils.Storage.SDevice;
import com.coocaa.x.service.XServiceManager;
import com.coocaa.x.service.litepm.aidl.ILitePMInstallListener;
import com.coocaa.x.service.litepm.aidl.ILitePMUninstallListener;
import com.coocaa.x.service.litepm.data.AppInfo;
import com.coocaa.x.service.litepm.data.InstallParams;
import com.tianci.appstore.R;
import com.tianci.appstore.controller.AppStoreBaseController;
import com.tianci.appstore.dataprovider.AppDataProvider;
import com.tianci.appstore.ui.data.APKData;
import com.tianci.appstore.ui.data.SkyAppDetailData.AppStatus;
import com.tianci.appstore.ui.list.scanapk.ScanAPKListListener;
import com.tianci.appstore.ui.widget.TipToast;
import com.tianci.appstore.utils.SkyConstants;
import com.tianci.appstore.utils.Tools;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class ScanAPKController extends AppStoreBaseController {
    private static final String tag = "scan";
    private static ScanAPKController instance = null;
    private ScanAPKListListener mScanAPKList = null;
    private boolean forceStop = false;
    private PackageManager pm = null;
    private boolean isSilent = false;
    // private APKData tempData = null;
    // private int installListSize = 0;

    private List<APKData> apkList = new ArrayList<APKData>();
    private List<String> pkgList = new ArrayList<String>();
    private List<APKData> needInstallList = new ArrayList<APKData>();
    private int installedSize = 0;
    // private List<APKData> installFailList = new ArrayList<APKData>();
    private static final String APPSTORE = "com.tianci.appstore";

    public static ScanAPKController getInstance() {
        if (instance == null) {
            instance = new ScanAPKController();
        }
        return instance;
    }

    public ScanAPKController() {
        pm = mContext.getPackageManager();
        // InstalledReceiver.addListener(this);
    }

    private ILitePMInstallListener.Stub installStub = new ILitePMInstallListener.Stub() {
        @Override
        public void onInstallEnd(String apkfile, AppInfo appInfo, int success, String extra, final InstallParams params)
                throws RemoteException {
            LogUtils.d("sinstall", "onInstallEnd!!!!!!" + success);
            pkgList.clear();
            if (mScanAPKList != null && success == 0) {
                AppStatus status = checkInstalled(appInfo.pkgName, appInfo.versionCode);
                if (status != AppStatus.HAS_NEW_VERSION)
                    mScanAPKList.onUpdateStatus(appInfo.pkgName, appInfo.versionCode, AppStatus.INSTALLED);
                else
                    mScanAPKList.onUpdateStatus(appInfo.pkgName, appInfo.versionCode, AppStatus.HAS_NEW_VERSION);
            }
            if (!isSilent) {
                return;
            }
            if (success == 0) {
                if (needInstallList != null && needInstallList.size() > 0) {
                    LogUtils.d("sinstall", "onInstallEnd---size:" + needInstallList.size());
                    installedSize++;
                    needInstallList.remove(0);
                    if (needInstallList.size() == 0) {
                        LogUtils.d("sinstall", "onInstallEnd--finish");
                        mScanAPKList.onInstallFinished(installedSize, null);
                        installedSize = 0;
                    } else {
                        installAPKList(needInstallList);
                    }
                }
            } else {
                LogUtils.d("sinstall", "onInstallEnd--failed!!!!!!!!!!!!" + installedSize);
                mScanAPKList.onInstallFinished(installedSize, needInstallList);
                installedSize = 0;
            }
        }

        @Override
        public void onInstallStart(String arg0, AppInfo appInfo, final InstallParams params) throws RemoteException {

        }
    };

    private ILitePMUninstallListener.Stub uninstallStub = new ILitePMUninstallListener.Stub() {

        @Override
        public void onUninstallEnd(AppInfo appInfo, int success, String extra)
                throws RemoteException {
            LogUtils.d("scan", "onUninstallEnd!!!!!!");
            pkgList.clear();
            if (mScanAPKList != null && success == 0)
                mScanAPKList.onUpdateStatus(appInfo.pkgName, 0, AppStatus.NOT_DOWNLOADED); // 获取不到version，所以全部pkg匹配（卸载可以）
        }

        @Override
        public void onUninstallStart(AppInfo appInfo) throws RemoteException {

        }
    };

    public void init() {
        runOnThread(new Runnable() {
            @Override
            public void run() {
                boolean isRoot = CoocaaApplication.isRoot();
                LogUtils.d("safe", "init isRoot:" + isRoot);
                boolean isSafe = isAppSaferOpen(mContext);
                isSilent = (isRoot && isSafe);
                try {
                    XServiceManager.getLitePMService().addInstallListener(installStub);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                try {
                    XServiceManager.getLitePMService().addUninstallListener(uninstallStub);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public void setScanAPKListener(ScanAPKListListener listener) {
        mScanAPKList = listener;
    }

    // public void resetInstallList(List<APKData> list)
    // {
    // needInstallList.clear();
    // tempData = null;
    // installListSize = list.size();
    // }

    public static boolean isAppSaferOpen(Context c) {
        int tag = Settings.Secure.getInt(c.getContentResolver(),
                Settings.Secure.INSTALL_NON_MARKET_APPS, 0);
        LogUtils.d("safe", "isAppSaferOpen:" + tag);
        return tag > 0;
    }

    public void clearList() {
        apkList.clear();
    }

    public void scanAPKOnThread() {
        runOnThread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                setForceStop(false);
                clearList();
                pkgList.clear();
                scanApkList(getScanPath());
                mScanAPKList.onFinishScan(apkList);
            }
        });
    }

    public void setForceStop(boolean f) {
        forceStop = f;
    }

    private List<String> getScanPath() {
        List<SDevice> devicesList = Storage.getSDeviceList();
        List<String> list = new ArrayList<String>();
        if (devicesList != null && devicesList.size() > 0) {
            for (SDevice device : devicesList) {
                LogUtils.d("scan", "getScanPath  mount point:" + device.getMountPoint());
                list.add(device.getMountPoint());
            }
        }
        return list;
//        return "/mnt/";
    }

    private synchronized void scanApkList(List<String> list) {
        if (list != null && list.size() > 0) {
            for (String path : list) {
                scanAPK(path);
            }
        }
    }

    private void scanAPK(String path) {
        // LogUtils.d(tag, "scanAPK--path:"+path);
        if (forceStop) {
            LogUtils.d("scan", "scanAPK---forceStop!!");
            return;
        }
        File rootDir = new File(path);
        if (!rootDir.exists()) {
            LogUtils.d(tag, "scanAPK---error path!!");
            // mScanAPKList.onFinishScan(apkList);
            return;
        }
        if (!rootDir.isDirectory()) {
            mScanAPKList.onShowCurrentPath(path);
            if (path.toLowerCase().endsWith(".apk")) {
                String filepath = rootDir.getAbsolutePath();
                LogUtils.d(tag, "scanAPK---" + filepath);
                getApkInfo(filepath);
            }
        } else {
            String[] fileList = rootDir.list();
            if (fileList != null && fileList.length > 0) {
                for (int i = 0; i < fileList.length; i++) {
                    if (!fileList[i].startsWith(".")) {
                        path = rootDir.getAbsolutePath() + "/" + fileList[i];
                        scanAPK(path);
                    }
                }
            }
        }
        return;
    }

    public void getApkInfo(String apkPath) {
        if (pm == null)
            pm = mContext.getPackageManager();
        PackageInfo pkgInfo = pm.getPackageArchiveInfo(apkPath, PackageManager.GET_ACTIVITIES);
        if (pkgInfo != null) {
            ApplicationInfo appInfo = pkgInfo.applicationInfo;
            /* 必须加这两句，不然下面icon获取是default icon而不是应用包的icon */
            appInfo.sourceDir = apkPath;
            appInfo.publicSourceDir = apkPath;
            String appName = pm.getApplicationLabel(appInfo).toString();// 得到应用名
            String packageName = appInfo.packageName; // 得到包名
            String versionName = pkgInfo.versionName; // 得到版本信息
            int version = pkgInfo.versionCode;
            String apkSize = "";
            long size = new File(appInfo.publicSourceDir).length() / SkyConstants.BTOK;
            float size2 = (float) size / SkyConstants.KTOM;
            if (size2 > 1.0f) {
                size2 = Tools.fixFloat(size2);
                apkSize = String.valueOf(size2) + "MB";
            } else {
                apkSize = String.valueOf(size) + "KB";
            }
            /* icon1和icon2其实是一样的 */
            Drawable icon1 = pm.getApplicationIcon(appInfo);// 得到图标信息
            // Drawable icon2 = appInfo.loadIcon(pm);
            APKData data = new APKData(appName, apkPath, getString(R.string.update_app_size)
                    + apkSize, icon1);
            data.setStatus(checkInstalled(packageName, version));
            // if (checkInstalled(packageName,version))
            // {
            // LogUtils.d("scan", "installed!!!!!!!!!!!!!!!");
            // data.setStatus(AppStatus.INSTALLED);
            // } else
            // {
            // data.setStatus(AppStatus.NOT_DOWNLOADED);
            // }
            // if(packageName.equals(APPSTORE)) //应用圈已经被service过滤了，这里补上
            // data.setStatus(AppStatus.INSTALLED);
            data.setVersionName(getString(R.string.update_app_version) + versionName);
            data.setPkgName(packageName);
            if (apkList != null && apkList.size() > 0) {
                for (APKData mAPKData : apkList) {
                    if (data.getPkgName().equals(mAPKData.getPkgName())
                            && data.getVersionName().equals(mAPKData.getVersionName())) {
                        LogUtils.d("scan", "the same apk!!!!!!!!!!!!!!");
                        return;
                    }
                }
            }
            apkList.add(data);
            // mScanAPKList.onRefreshScanList(apkList);
            String pkgInfoStr = String.format("PackageName:%s, Vesion: %s, AppName: %s, size: %s",
                    packageName, versionName, appName, apkSize);
            LogUtils.d("scan", String.format("PkgInfo: %s", pkgInfoStr));
        } else {
            LogUtils.d("scan", "fake apk!!!!!!!!!");
            return;
        }
    }

    public AppStatus checkInstalled(String pkg, int versionCode) {
        AppStatus status = AppDataProvider.getInstance().getAppStatus(pkg,
                String.valueOf(versionCode));
        LogUtils.d("as", "pkg  :" + pkg + " versionCode:" + versionCode + " status:" + status);
        return status;
    }

    public void installAPK(APKData data) {
        String path = data.getPath();
        LogUtils.d("sinstall", "installAPK:" + path);
        if (!new File(path).exists()) {
            LogUtils.d("sinstall", "file is dismiss!!!");
            TipToast.getInstance(mContext).showTipToast("安装的应用不存在！");
            if (isSilent) {
                mScanAPKList.onInstallFinished(installedSize, needInstallList);
                installedSize = 0;
            }
            return;
        }
        try {
            // XServiceManager.getLitePMService().install(path, isSilent);
            InstallParams params = new InstallParams();
            params.setFrom(InstallParams.INSTALL_FROM.LOCAL_DISK);
            if (isSilent)
                XServiceManager.getLitePMService().install(path, isSilent, params);
            else
                XServiceManager.getLitePMService().installWithSP(path, params);
        } catch (RemoteException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            LogUtils.d("sinstall", "error!!!!!!");
            TipToast.getInstance(mContext).showTipToast("安装应用出错！");
            if (isSilent) {
                mScanAPKList.onInstallFinished(installedSize, needInstallList);
                installedSize = 0;
            }
        }
    }

    public void installAPKList(List<APKData> list) {
        // tempData = list.remove(0);
        if (list == null || list.size() < 1) {
            mScanAPKList.onInstallFinished(0, null);
            return;
        }
        needInstallList = null;
        needInstallList = new ArrayList<APKData>();
        needInstallList.addAll(list);
        LogUtils.d("sinstall", "installAPKList---------list.size:" + needInstallList.size());
        installAPK(needInstallList.get(0));
    }

    @Override
    public void destroy() {
        // TODO Auto-generated method stub
        installedSize = 0;
        setForceStop(true);
        runOnThread(new Runnable() {

            @Override
            public void run() {
                try {
                    XServiceManager.getLitePMService().removeInstallListener(installStub);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                try {
                    XServiceManager.getLitePMService().removeUninstallListener(uninstallStub);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
        mScanAPKList = new ScanAPKListListener() {
            @Override
            public void onShowCurrentPath(String path) {

            }

            @Override
            public void onFinishScan(List<APKData> list) {

            }

            @Override
            public void onInstallFinished(int successCount, List<APKData> failList) {

            }

            @Override
            public void onUpdateStatus(String pkgName, int version, AppStatus status) {

            }
        };
    }
}
